package com.arpa.wms.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.arpa.core.web.Result;
import com.arpa.ntocc.common.common.cache.PartyCache;
import com.arpa.ntocc.common.common.util.CommonUtil;
import com.arpa.ntocc.common.common.util.UserUtil;
import com.arpa.wms.domain.consts.NumConst;
import com.arpa.wms.domain.dto.InventoryOperationDto;
import com.arpa.wms.domain.dto.OutboundRegisterDTO;
import com.arpa.wms.domain.entity.OutboundRegister;
import com.arpa.wms.domain.enums.OutboundRecheckStatusEnum;
import com.arpa.wms.domain.enums.OutboundStatusEnum;
import com.arpa.wms.domain.vo.OutboundRegisterVO;
import com.arpa.wms.mapper.OutboundRegisterMapper;
import com.arpa.wms.service.IOutboundRegisterService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 出库单明细 服务实现类
 * </p>
 *
 * @author LEO
 * @since 2020-10-27
 */
@Service
public class OutboundRegisterServiceImpl extends ServiceImpl<OutboundRegisterMapper, OutboundRegister> implements IOutboundRegisterService {

    @Autowired
    private PartyCache partyCache;

    /**
     * 保存
     * @param entity
     * @return
     */
    @Override
    @Transactional(rollbackFor={Exception.class})
    public boolean save(OutboundRegister entity) {
        if(StringUtils.isBlank(entity.getCode())){
            entity.setCode(IdUtil.simpleUUID());
        }
        entity.setGroupCode(UserUtil.getBranchCode());
        if(StringUtils.isBlank(entity.getCreatedBy())){
            entity.setCreatedBy(UserUtil.getCode());
        }
        return super.save(entity);
    }

    /**
     * 根据code更新实体
     * @param entity
     * @return
     */
    @Override
    @Transactional(rollbackFor={Exception.class})
    public int updateByCode(OutboundRegister entity) {
        if(StringUtils.isBlank(entity.getModifiedBy())){
            entity.setModifiedBy(UserUtil.getCode());
        }
        return baseMapper.update(entity,new QueryWrapper<OutboundRegister>().lambda().eq(OutboundRegister::getCode,entity.getCode()).eq(OutboundRegister::getGroupCode,UserUtil.getBranchCode()));
    }

    /**
     * 查询列表
     * @param outboundRegisterDTO
     * @return
     */
    @Override
    public List<OutboundRegisterVO> queryList(OutboundRegisterDTO outboundRegisterDTO){
        outboundRegisterDTO.setGroupCode(UserUtil.getBranchCode());
        //排序字段名需要驼峰转数据库下划线类型字段名
        if(StringUtils.isNotEmpty(outboundRegisterDTO.getSortField())){
            outboundRegisterDTO.setSortField(CommonUtil.camel2Underline(outboundRegisterDTO.getSortField()));
        }
        List<OutboundRegisterVO> outboundRegisterVOList = baseMapper.queryList(outboundRegisterDTO);
        return outboundRegisterVOList;
    }

    /**
     * 查询合计,包含总数
     * @param outboundRegisterDTO
     * @return
     */
    @Override
    public OutboundRegisterVO queryListSum(OutboundRegisterDTO outboundRegisterDTO){
        outboundRegisterDTO.setGroupCode(UserUtil.getBranchCode());
        OutboundRegisterVO outboundRegisterVO = baseMapper.queryListSum(outboundRegisterDTO);
        return outboundRegisterVO;
    }

    /**
     * 根据出库单、商品编码、确认状态查询出库复核单列表
     *
     * @param outboundRegisterDTO :
     * @return
     */
    @Override
    public List<OutboundRegisterVO> queryRegisterList(OutboundRegisterDTO outboundRegisterDTO) {
        List<OutboundRegisterVO> vos = this.queryList(outboundRegisterDTO);
        return vos;
    }

    /**
     * @param register :
     * @description 保存，如果存在相同信息的出库复核信息，则合并
     * @author xuyang
     * @date 2020/10/29 8:21
     **/
    @Override
    public Result distinctSave(OutboundRegister register) {
        // 查询是否有相同明细下、已复核的数据
        OutboundRegister sameOne = this.getOne(new QueryWrapper<OutboundRegister>().lambda().eq(OutboundRegister::getDeleted,0)
                .eq(OutboundRegister::getGroupCode,UserUtil.getBranchCode())
                .eq(OutboundRegister::getOutboundItemCode, register.getOutboundItemCode()).eq(OutboundRegister::getStatus, OutboundRecheckStatusEnum.RECHECKED.getValue()));

        if(sameOne != null){
            // 如果存在则在原基础上增加复核数量
            this.update(new UpdateWrapper<OutboundRegister>().lambda().eq(OutboundRegister::getCode, sameOne.getCode())
                    .eq(OutboundRegister::getGroupCode,UserUtil.getBranchCode())
                        .setSql(" recheck_quantity = recheck_quantity + " + register.getRecheckQuantity()));
        }else{
            register.setCode(StrUtil.EMPTY);
            register.setCreatedBy(StrUtil.EMPTY);
            register.setModifiedBy(StrUtil.EMPTY);
            register.setStatus(OutboundRecheckStatusEnum.RECHECKED.getValue());
            register.setOperatorBy(UserUtil.getCode());
            register.setOperatorName(partyCache.translate(UserUtil.getCode()));
            save(register);
        }
        return Result.ok();
    }

    /**
     * 更新复核数量
     * @author liuxr
     * @date 2021/4/12 18:45
     * @param outboundCode 出库单号
     * @param oldInventoryCode 原库存code
     * @param reviewCount 复核数量
     * @return int 更新条数
     */
    @Override
    public int generalReviewUpdateInfo( String outboundCode,  String oldInventoryCode,  BigDecimal reviewCount,String groupCode,boolean updateNotRecheckQuantity){
        return this.baseMapper.generalReviewUpdateInfo(outboundCode, oldInventoryCode, reviewCount,groupCode,updateNotRecheckQuantity);
    }
    /**
     * 订单取消更新出库确认明细数量
     *
     * @param wavePickingCode
     * @param allQuantityList
     * @author liuxr
     * @date 2021/5/21 21:23
     */
    @Override
    public void deliveryCancelUpdataQuantity(String wavePickingCode, List<InventoryOperationDto> allQuantityList) {
        this.baseMapper.deliveryCancelUpdataQuantity(wavePickingCode,allQuantityList,UserUtil.getBranchCode());
    }

    /**
     * 根据波次号和状态查询列表
     * @param outboundRegisterDTO
     * @return
     */
    @Override
    public List<OutboundRegisterVO> queryListGroupByWavePickingCodeAndStatus(OutboundRegisterDTO outboundRegisterDTO){
        outboundRegisterDTO.setGroupCode(UserUtil.getBranchCode());
        return this.baseMapper.queryListGroupByWavePickingCodeAndStatus(outboundRegisterDTO);
    }

    /**
     * 更新复核数量及状态
     * @author rfwang
     * @date 2022年3月16日
     * @param outboundCode 出库单号
     * @param deliveryItemCode 订单明细号
     * @param reviewCount 复核数量
     * @return int 更新条数
     */
    @Override
    public int updateRecheckQuantityAndStatus( String outboundCode,  String deliveryItemCode,  BigDecimal reviewCount,String groupCode){
        //这里主要处理一个商品在一个库位的不同库存下的情况
        List<OutboundRegister> outboundRegisters = this.list(new LambdaQueryWrapper<OutboundRegister>().eq(OutboundRegister::getDeliveryItemCode, deliveryItemCode));
        BigDecimal remainRecheckQuantity = reviewCount;
        int updateNum = 0;
        //一个出库明细对应多个出库登记的逻辑
        if (outboundRegisters.size() > 1) {
            List<String> statuses = new ArrayList<>(Arrays.asList(OutboundStatusEnum.NOT_RECHECK.getValue(), OutboundStatusEnum.RECHECKING.getValue()));
            //获取待复核和复核中的复核登记信息
            List<OutboundRegister> outboundRegisterList = outboundRegisters.stream().filter(e -> statuses.contains(e.getStatus())).collect(Collectors.toList());
            for (OutboundRegister register : outboundRegisterList) {
                BigDecimal recheckQuantity = remainRecheckQuantity.compareTo(register.getRecheckQuantity()) >= 0 ? register.getPlanQuantity() : remainRecheckQuantity;
                remainRecheckQuantity = remainRecheckQuantity.subtract(recheckQuantity);
                //更新明细复核数量
                updateNum += this.generalReviewUpdateInfo(outboundCode,register.getOldInventoryCode(),recheckQuantity,groupCode,true);
                if (remainRecheckQuantity.compareTo(BigDecimal.ZERO) == 0) {
                    return updateNum;
                }
            }

        }
        return this.generalReviewUpdateInfo(outboundCode,outboundRegisters.get(NumConst.NUM_ZERO).getOldInventoryCode(),remainRecheckQuantity,groupCode,true);
    }

}
